Skip to content

fix: wiki multi-level headings, tag hierarchy scope, and baseline advance#178

Open
bk-ty wants to merge 1 commit intokenforthewin:mainfrom
bk-ty:fix/wiki-improvements
Open

fix: wiki multi-level headings, tag hierarchy scope, and baseline advance#178
bk-ty wants to merge 1 commit intokenforthewin:mainfrom
bk-ty:fix/wiki-improvements

Conversation

@bk-ty
Copy link
Copy Markdown
Contributor

@bk-ty bk-ty commented Apr 30, 2026

Summary

Three related fixes to wiki generation and the update proposal flow.


1. Multi-level heading support

Problem: The section parser only recognised ## headings; ### and deeper headings were swallowed into the nearest h2 body, making them invisible to ops like AppendToSection and ReplaceSection. The LLM-facing heading list also showed a flat ## foo prefix, obscuring document hierarchy.

Fix (section_ops.rs, wiki/mod.rs):

  • Parser now treats any ##+ heading as a section boundary
  • extract_current_headings returns (level, text) pairs; the prompt renders sub-headings with indentation so the LLM can see the hierarchy
  • apply_section_ops switches to soft-fail: a bad op (hallucinated heading) is skipped and reported rather than aborting the entire update
  • Prompt copy updated from "## headings" to "section headings" to avoid confusing models about depth

Tests updated and extended (25 tests, all pass).


2. Tag hierarchy scope for wiki queries

Problem: get_new_atoms_since and the atom_count used in update_wiki only queried atoms directly tagged with the exact tag_id. get_article_status (which drives the "N new atoms" banner) uses a recursive CTE to count across the full descendant tree. The mismatch caused spurious banners for atoms in child tags that the update logic never actually passed to the LLM.

Fix (sqlite/wiki.rs, postgres/wiki.rs): Both queries now use the same recursive descendant CTE as get_article_status, so counts are always consistent.


3. Advance baseline when no update is warranted

Problem: When generate_wiki_update ran but the LLM found nothing worth changing, the article's atom_count and updated_at were not updated. Every subsequent "Generate Update" click re-evaluated the same atoms, and the "N new atoms" banner never cleared.

Fix (lib.rs, storage/traits.rs, storage/mod.rs, sqlite/wiki.rs, postgres/wiki.rs):

  • New advance_wiki_baseline storage method bumps atom_count and updated_at without changing article content
  • Called from generate_wiki_update when no proposal is created
  • accept_wiki_proposal now uses proposal.created_at instead of a fresh Utc::now() for updated_at

Testing

  • cargo test -p atomic-core section_ops — 25/25 pass
  • cargo test -p atomic-core wiki — all pass including test_wiki_article_lifecycle
  • cargo check -p atomic-core — clean

…ance

Three related fixes to wiki generation and the update proposal flow:

Multi-level heading support (section_ops.rs, wiki/mod.rs):
- Parser now recognises h3+ headings as addressable sections instead of
  swallowing them into the nearest h2 body. heading and after_heading
  fields in ops can now reference any ## or deeper heading.
- extract_current_headings returns (level, text) pairs; the prompt
  renders sub-headings with indentation so the LLM sees the hierarchy.
- apply_section_ops switches to a soft-fail mode per op: if a single
  op references a hallucinated heading, the rest still apply and the
  bad op is reported in the returned error list rather than aborting the
  whole update.
- Prompt wording updated: '## headings' -> 'section headings' to avoid
  confusing models that generate h3+ content.

Tag hierarchy scope (sqlite/wiki.rs, postgres/wiki.rs):
- get_new_atoms_since and atom_count queries now use a recursive CTE to
  span the full tag descendant tree, matching the scope used by
  generation and get_article_status. Previously these queries only
  looked at atoms directly tagged with the exact tag_id, causing the
  'N new atoms' banner to miscount atoms in child tags and fire
  spuriously.

Advance baseline on no-op updates (lib.rs, storage/traits.rs,
storage/mod.rs, sqlite/wiki.rs, postgres/wiki.rs):
- When generate_wiki_update finds no changes worth proposing, it now
  calls advance_wiki_baseline to bump atom_count and updated_at to
  current values. This clears the 'N new atoms' banner and prevents
  the same atoms from being re-evaluated on every subsequent
  'Generate Update' click.
- accept_wiki_proposal: use proposal.created_at instead of a fresh
  Utc::now() for updated_at so the stored timestamp matches the
  proposal's age rather than the accept time.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant